#ifdef __cplusplus



#endif
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory>
#include <sys/socket.h>
#include <atomic>
#include  <unistd.h>


#include <libudev.h>
#include <iostream>
#include <string>
#include <fstream>

#if 0
#include <arm_neon.h>  // 需要添加NEON头文件
#endif

#include "cmdutils.h"
#include "blur_interface.h"

#include "display.h"
#include "camera.h"

#define BUF_SIZE 4096

#define WIDTH 640
#define HEIGHT 480
#define BPP 4

// 高斯模糊核（3x3）
static const float gaussian_kernel_7x7[49] = {
    1.0f / 256,  4.0f / 256,  7.0f / 256,  4.0f / 256,  7.0f / 256,  4.0f / 256, 1.0f / 256,
    4.0f / 256, 16.0f / 256, 26.0f / 256, 24.0f / 256, 26.0f / 256, 16.0f / 256, 4.0f / 256,
    7.0f / 256, 26.0f / 256, 41.0f / 256, 36.0f / 256, 41.0f / 256, 26.0f / 256, 7.0f / 256,
    4.0f / 256, 24.0f / 256, 36.0f / 256, 32.0f / 256, 36.0f / 256, 24.0f / 256, 4.0f / 256,
    7.0f / 256, 26.0f / 256, 41.0f / 256, 36.0f / 256, 41.0f / 256, 26.0f / 256, 7.0f / 256,
    4.0f / 256, 16.0f / 256, 26.0f / 256, 24.0f / 256, 26.0f / 256, 16.0f / 256, 4.0f / 256,
    1.0f / 256,  4.0f / 256,  7.0f / 256,  4.0f / 256,  7.0f / 256,  4.0f / 256, 1.0f / 256
};
// 高斯模糊函数
static void apply_gaussian_blur(SDL_Surface *src, SDL_Surface *dst) 
{
    int width = src->w;
    int height = src->h;
    Uint32 *src_pixels = (Uint32 *)src->pixels;
    Uint32 *dst_pixels = (Uint32 *)dst->pixels;

    for (int y = 3; y < height - 3; y++) {
        for (int x = 3; x < width - 3; x++) {
            float r = 0, g = 0, b = 0;
            for (int ky = -3; ky <= 3; ky++) {
                for (int kx = -3; kx <= 3; kx++) {
                    int px = x + kx;
                    int py = y + ky;
                    Uint32 pixel = src_pixels[py * width + px];
                    Uint8 red, green, blue;
                    SDL_GetRGB(pixel, src->format, &red, &green, &blue);
                    int kernel_index = (ky + 3) * 7 + (kx + 3); // 计算7x7核索引
                    r += red * gaussian_kernel_7x7[kernel_index];
                    g += green * gaussian_kernel_7x7[kernel_index];
                    b += blue * gaussian_kernel_7x7[kernel_index];
                }
            }
            Uint32 blurred_pixel = SDL_MapRGB(dst->format, (Uint8)r, (Uint8)g, (Uint8)b);
            dst_pixels[y * width + x] = blurred_pixel;
        }
    }
}
//sudo mount 192.168.5.3:/opt /opt
//cd /opt/FFmpeg_Gaussian-Blur/build/rockchip/
static const std::string count_file = "/userdata/run_count.dat"; // 计数器文件路径
static int count = 0;
bool checkAndIncrementRunCount() {
    std::ifstream inFile(count_file);
    
    if (inFile.is_open()) {
        inFile >> count;
        inFile.close();
    }

    if (count >= 1500) {
        fprintf(stderr, "Error: Program has been run %d times. Maximum allowed is 500.\n", count);
        return false;
    }

    count++;
    

    std::ofstream outFile(count_file);
    if (outFile.is_open()) {
        outFile << count;
        outFile.close();
    }

    return true;
}

static int show_original = 0; // 默认不显示原始窗口
static int show_blurred  = 1; // 默认显示模糊窗口
static const char *input_filename = NULL;
static enum SDL2Player::SDLWindowsFlag window_flags = SDL2Player::SDLWindowsFlag::SDL_WINDOW_SHOWN;
static uint32_t out_width = WIDTH,out_height = HEIGHT;
static uint32_t src_width = 0,src_height = 0;
static void show_original_handler(const char *arg) 
{
    printf("Enabling original video window.\n");
    show_original = 1;
}
static void no_show_blurred_handler(const char *arg) 
{
    printf("Disable blurred video window.\n");
    show_blurred = 0;
}
static void fullscreen_windows_handler(const char *arg) 
{
    printf("Enable full screen window.\n");
    window_flags = SDL2Player::SDLWindowsFlag::SDL_WINDOW_FULLSCREEN_DESKTOP;
    
}

static void input_file_handler(const char *filename) 
{
    printf("Input file set to: %s\n", filename);
    input_filename = filename;
}
static void input_width_handler(const char *width) 
{
    printf("width set to: %s\n", width);
    out_width = atoi(width);
}
static void input_height_handler(const char *height) 
{
    printf("height set to: %s\n", height);
    out_height = atoi(height);
}

static Option options[] = {
    { "original-show", 0, show_original_handler },
    { "blurred-no-show", 0, no_show_blurred_handler },
    { "fullscreen", 0, fullscreen_windows_handler },
    { "-i", 1, input_file_handler },
    { "-w", 1, input_width_handler },
    { "-h", 1, input_height_handler },
    { NULL }
};

enum PixelFormat {
    UNKNOWN,
    RGB24,
    BGR24,
    YUYV422,
    NV12,
    NV21,
};
#if 0
static void calculateRowAverageColors(
                            const std::vector<char>& videoData, 
                            int width, int height, 
                            PixelFormat format,
                            std::vector<char>& outAverages)
{
    if (videoData.empty()) {
        printf("videoData is empty\n");
        return;
    }

    outAverages.clear();
    outAverages.resize(width * height * 3); // 预分配空间避免多次push_back

    const uint8_t* pixelData = reinterpret_cast<const uint8_t*>(videoData.data());

    switch (format) {
        case PixelFormat::RGB24: {
            #pragma omp parallel for // 启用多线程并行
            for (int y = 0; y < height; ++y) {
                uint32x4_t r_sum = vdupq_n_u32(0);
                uint32x4_t g_sum = vdupq_n_u32(0);
                uint32x4_t b_sum = vdupq_n_u32(0);
                int processed = 0;

                // NEON处理核心部分 (每次处理16像素)
                for (int x = 0; x + 16 <= width; x += 16) {
                    // 加载48字节数据(16像素x3通道)
                    uint8x16x3_t rgb = vld3q_u8(pixelData + (y * width + x) * 3);
                    
                    // 将8位数据扩展为16位
                    uint16x8_t r_low = vmovl_u8(vget_low_u8(rgb.val[0]));
                    uint16x8_t r_high = vmovl_u8(vget_high_u8(rgb.val[0]));
                    uint16x8_t g_low = vmovl_u8(vget_low_u8(rgb.val[1]));
                    uint16x8_t g_high = vmovl_u8(vget_high_u8(rgb.val[1]));
                    uint16x8_t b_low = vmovl_u8(vget_low_u8(rgb.val[2]));
                    uint16x8_t b_high = vmovl_u8(vget_high_u8(rgb.val[2]));
                    
                    // 累加到32位寄存器
                    r_sum = vaddq_u32(r_sum, vaddl_u16(vget_low_u16(r_low), vget_high_u16(r_low)));
                    g_sum = vaddq_u32(g_sum, vaddl_u16(vget_low_u16(g_low), vget_high_u16(g_low)));
                    b_sum = vaddq_u32(b_sum, vaddl_u16(vget_low_u16(b_low), vget_high_u16(b_low)));
                    
                    processed += 16;
                }

                // 计算总和
                uint32_t total_r = vgetq_lane_u32(r_sum, 0) + vgetq_lane_u32(r_sum, 1) +
                                  vgetq_lane_u32(r_sum, 2) + vgetq_lane_u32(r_sum, 3);
                uint32_t total_g = vgetq_lane_u32(g_sum, 0) + vgetq_lane_u32(g_sum, 1) +
                                  vgetq_lane_u32(g_sum, 2) + vgetq_lane_u32(g_sum, 3);
                uint32_t total_b = vgetq_lane_u32(b_sum, 0) + vgetq_lane_u32(b_sum, 1) +
                                  vgetq_lane_u32(b_sum, 2) + vgetq_lane_u32(b_sum, 3);

                // 处理剩余像素(非16倍数部分)
                for (int x = processed; x < width; ++x) {
                    int idx = (y * width + x) * 3;
                    total_r += pixelData[idx];
                    total_g += pixelData[idx + 1];
                    total_b += pixelData[idx + 2];
                }

                // 计算平均值
                uint8_t avg_r = total_r / width;
                uint8_t avg_g = total_g / width;
                uint8_t avg_b = total_b / width;

                // 使用NEON批量填充平均值
                uint8x16_t avg_r_vec = vdupq_n_u8(avg_r);
                uint8x16_t avg_g_vec = vdupq_n_u8(avg_g);
                uint8x16_t avg_b_vec = vdupq_n_u8(avg_b);
                
                // 批量存储
                for (int x = 0; x + 16 <= width; x += 16) {
                    int out_idx = (y * width + x) * 3;
                    uint8_t* out_ptr = outAverages.data() + out_idx;
                    vst3q_u8(out_ptr, {avg_r_vec, avg_g_vec, avg_b_vec});
                }

                // 处理剩余部分
                for (int x = width - (width % 16); x < width; ++x) {
                    int out_idx = (y * width + x) * 3;
                    outAverages[out_idx] = avg_r;
                    outAverages[out_idx + 1] = avg_g;
                    outAverages[out_idx + 2] = avg_b;
                }
            }
            break;
        }

        default:
            printf("Unsupported pixel format in calculateRowAverageColors\n");
            return;
    }
}
#endif
static void calculateRowAverageColors(
                            const std::vector<char>& videoData, 
                            int width, int height, 
                            PixelFormat format,
                            std::vector<char>& outAverages)
{
    if (videoData.empty()) {
        printf("videoData is empty\n");
        return;
    }

    outAverages.clear();
    outAverages.reserve(height * 3); // 每行 3 字节 RGB 平均值

    const Uint8* pixelData = reinterpret_cast<const Uint8*>(videoData.data());

    switch (format) {
        case PixelFormat::RGB24:
            for (int y = 0; y < height; ++y) {
                int rSum = 0, gSum = 0, bSum = 0;
                for (int x = 0; x < width; ++x) {
                    int index = (y * width + x) * 3;
                    if (index + 2 >= videoData.size()) 
                            break;
                    rSum += pixelData[index + 0];
                    gSum += pixelData[index + 1];
                    bSum += pixelData[index + 2];
                }
                for (int x = 0; x < width; ++x) { 
                    outAverages.push_back(rSum / width);
                    outAverages.push_back(gSum / width);
                    outAverages.push_back(bSum / width);
                }

                
                
            }
            break;

        default:
            printf("Unsupported pixel format in calculateRowAverageColors\n");
            return;
    }
}

std::vector<char> outAverages;
std::atomic<uint8_t> run(1);

int main(int argc, char *argv[]) 
{

    // if (!checkAndIncrementRunCount()) {
    //     printf("超过 500 次，不启动程序\n");
    //     return -1; // 超过 500 次，不启动程序
    // }else {
    //     printf("当前运行次数：%d\n", count);
    // }

    if(argc < 2) {
        fprintf(stderr, "Usage: %s <-i input_file> [original-show] [blurred-no-show]\n", argv[0]);
        return -1;
    }
    if (parse_options(options, argc, argv) < 0) {
        fprintf(stderr, "Invalid command line arguments.\n");
        return -1;
    }

    struct udev *udev = udev_new();
    if (!udev) {
        std::cerr << "Failed to create udev context.\n";
        return -1;
    }

 
    std::shared_ptr<SDL2Player> SDLdisp_original = std::make_shared<SDL2Player>();
    std::shared_ptr<SDL2Player> SDLdisp_blurred = std::make_shared<SDL2Player>();

    std::shared_ptr<camera> Cam = std::make_shared<camera>(input_filename);
    camera::camera_info *info =nullptr;

    enum SDL2Player::SDLEvent env;

    int left_x= 0;
    int left_y= 0;
    int right_x= 0;
    int right_y= 0;

    if(show_original){
        
        SDLdisp_original->GetCurrentScreenSize(src_width,src_height);
        if(show_original && show_blurred){
            left_x = (src_width / 2 - src_height) / 2;
            left_y = 100;
        }else{
            left_x = SDL_WINDOWPOS_UNDEFINED;
            left_y = SDL_WINDOWPOS_UNDEFINED;
        }
        if(window_flags == SDL2Player::SDLWindowsFlag::SDL_WINDOW_FULLSCREEN_DESKTOP){
            out_width = src_width;
            out_height = src_height;
        }
        SDLdisp_original->Init(out_width,out_height,SDL2Player::PixFormat::RGB);
        SDLdisp_original->CreateRenderWindow(window_flags,left_x,left_y);   
    }
    if(show_blurred){
        if(show_original && show_blurred){
            right_x  = left_x + out_width + 100;
            right_y   = 100;
        }else{
            right_x = SDL_WINDOWPOS_UNDEFINED;
            right_y = SDL_WINDOWPOS_UNDEFINED;
        }
        SDLdisp_blurred->GetCurrentScreenSize(src_width,src_height);
        if(window_flags == SDL2Player::SDLWindowsFlag::SDL_WINDOW_FULLSCREEN_DESKTOP){
            out_width = src_width;
            out_height = src_height;
        }
        SDLdisp_blurred->Init(out_width,out_height,SDL2Player::PixFormat::RGB);
        SDLdisp_blurred->CreateRenderWindow(window_flags,right_x,right_y);  
    }
    
    outAverages.reserve(out_width*out_height*3); // 每行 3 字节 RGB 平均值
    printf("outAverages.size = %d \n",outAverages.size());

    info = Cam->camera_init(out_width,out_height,camera::Cam_pixelformat::PIXEL_RGB,
    [&](std::vector<char > videoData,int  width,int height,void *p)->int{
        

        if(show_original)
            SDLdisp_original->Render((char *)videoData.data());
        if(show_blurred){
            calculateRowAverageColors(videoData,out_width,out_height,RGB24,outAverages);
            if(outAverages.size() >= width*height*3){
                // printf("Blurred %d %d width=%d height=%d \n",
                // videoData.size(),outAverages.size(),width,height);
                SDLdisp_blurred->Render((char *)outAverages.data());
            } 
            // SDLdisp_blurred->Render((char *)videoData.data());    
        }
              
        return  0;
    },
    [&](int errorCode)->int{
        printf("quit \n");
        run.store(0);
        printf("set run=%d \n",run.load());
        
        
        return 0;
    },
    nullptr);

    while(run.load()){
        if (!run.load()) 
            break;
        if(show_original){
            env = SDLdisp_original->GetEvent();
            if (env !=  SDL2Player::SDLEvent::NOTHING){
                run.store(0, std::memory_order_release);
                break; 
            }
                 
        }
        
        if(show_blurred){
            env = SDLdisp_blurred->GetEvent();
            if (env !=  SDL2Player::SDLEvent::NOTHING){
                run.store(0, std::memory_order_release);
                break; 
            }
        }
        usleep(1000); 
    }
    printf("program quit\n");
    return 0;
}